package cn.com.kh;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class KHFileUtil {
    private static final Log log = LogFactory.getLog(KHFileUtil.class);

    /**
     * @param fileContent: 写入内容
     * @param FilePath:    写入文件路径(含文件名)
     * @return boolean
     * @author LiJT
     * @description TODO 将字符串内容写入到文件
     * @date 2023-01-31 10:50
     */
    public static boolean writeFile(String fileContent, String FilePath) {

        long tstartTime, tendTime, startTime, endTime;

        tstartTime = System.currentTimeMillis();
        log.debug("-File写入本地文件参数 Start time:" + tstartTime + "-emlFilePath:" + FilePath);

        // 将文件内容写入本地服务器
        int i = 0;
        File dirAll = new File(FilePath);
        FileWriter fw = null;
        startTime = System.currentTimeMillis();

        log.debug("-File[" + i + "]开始将文件内容写入本地服务器:" + "-FilePath:" + FilePath);
        try {
            // 文件夹路径是否存在不存在则创建
            File dir = new File(dirAll.getParent());
            if (!dir.exists()) {
                log.debug("-File[" + i + "]创建所需路径:" + dirAll.getParent());
                dir.mkdirs();
            }

            // 检查目标文件是否存在，不存在则创建
            if (!dirAll.exists()) {
                log.debug("-File[" + i + "]创建写入文件:" + dirAll.getName());
                dirAll.createNewFile();
            }
            // 向目标文件中写入内容
            fw = new FileWriter(FilePath, false);
            fw.write(fileContent);
            fw.flush();

            fw.close();

            log.debug("-File[" + i + "]写入文件完成...");

        } catch (Exception e) {
            log.error("-File[" + i + "]写入文件失败：", e);
            e.printStackTrace();
        } finally {
            try {
                if (fw != null) {
                    fw.close();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                log.warn("文件操作对象释放异常-", e);
            }
            endTime = System.currentTimeMillis();

            log.debug("-File[" + i + "]写入文件结束 Start time:" + startTime + "; End time:" + endTime + "; Run Time:" + (endTime - startTime) + "(ms)");

            i++;

        }

        tendTime = System.currentTimeMillis();
        log.debug("-File写入本地文件结束 End time:" + tendTime + "; Run Time:" + (tendTime - tstartTime) + "(ms)");

        return dirAll.exists();

    }

    /**
     * @param cmdStr: 执行命令
     * @return boolean 成功true 失败false
     * @author LiJT
     * @description TODO 执行Linux命令
     * @date 2023-01-31 10:54
     */
    public static boolean doLinuxCmd(String cmdStr) {

        log.debug("doLinuxCmd command:" + cmdStr);
        boolean flag = false;
        List<String> command = new ArrayList<>();
        command.add("/bin/sh");
        command.add("-c");
        command.add(cmdStr);
        try {
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true);
            Process process = builder.start();
            LineNumberReader ir = new LineNumberReader(new InputStreamReader(process.getInputStream(), Charset.forName("UTF8")));
            String lines = new String(), line;
            while ((line = ir.readLine()) != null) {
                lines += line;
                log.debug("doLinuxCmd 执行过程:" + line);
            }
            log.debug("doLinuxCmd 执行结果:" + lines);

            if (process.isAlive()) {
                int exitcode = process.waitFor();
                if (exitcode == 0) {
                    flag = true;
                    log.debug("doLinuxCmd successfully");
                } else {
                    log.error("doLinuxCmd failed and return " + exitcode);
                }
            }
        } catch (Exception e) {
            log.error("doLinuxCmd Exception-", e);
        }
        return flag;
    }

    /**
     * @param dirPath: 文件夹路径
     * @return String 数组
     * @author LiJT
     * @description TODO 读取文件夹下所有文件和目录
     * @date 2023-01-31 11:00
     */
    public static String[] getDirList(String dirPath) {
        log.debug("getDirList 待读取路径:" + dirPath);
        String[] list = null;
        File file = new File(dirPath);
        if (file.isDirectory()) {
            log.debug("getDirList 正在读取[" + dirPath + "]目录....");
            list = file.list();
        } else {
            log.debug("getDirList[" + dirPath + "]不是一个目录。");
        }
        return list;
    }

    /**
     * 删除单个文件
     *
     * @param pathName 删除文件路径名
     * @return
     */
    public static boolean deleteFiles(String pathName) {
        boolean flag = false;
        //根据路径创建文件对象
        File file = new File(pathName);
        //路径是个文件且不为空时删除文件
        if (file.isFile() && file.exists()) {
            flag = file.delete();
        }
        //删除失败时，返回false
        return flag;
    }

    /**
     * 删除目录本身以及目录下的所有文件及文件夹
     *
     * @param pathName 目录名
     * @return
     */
    public static boolean deleteDiretory(String pathName) {
        boolean flag = false;
        //根据路径创建文件对象
        File directory = new File(pathName);
        //如果路径是一个目录且不为空时，删除目录
        if (directory.isDirectory() && directory.exists()) {
            //获取目录下的所有的目录和文件，放入数组files中
            File[] files = directory.listFiles();
            //遍历目录下的所有的文件和目录
            for (int i = 0; i < files.length; i++) {
                //如果目录下是文件时，调用deleteFiles（）方法，删除单个文件
                if (files[i].isFile()) {
                    flag = deleteFiles(files[i].getAbsolutePath());
                }//如果目录下是目录时，调用自身deleteDirectory()，形成递归调用
                else {
                    flag = deleteDiretory(files[i].getAbsolutePath());
                }
            }

            //删除目录本身，如果想要保留目录只删除文件，此句可以不要
            flag = directory.delete();
        }
        //删除成功时返回true，失败时返回false
        return flag;
    }

    /**
     * 删除文件或者目录
     *
     * @param pathName 路径名
     * @return
     */
    public static boolean deleteDirectoryOrFile(String pathName) {
        boolean flag = false;
        File file = new File(pathName);
        //如果路径是一个文件则调用deleteFiles()
        if (file.isFile() && file.exists()) {
            flag = deleteFiles(pathName);
        }//如果路径是目录则调用deleteDirectory()
        else if (file.isDirectory() && file.exists()) {
            flag = deleteDiretory(pathName);
        }

        return flag;
    }

}
